/*
 * d.c
 *
 *  Created on: Sep 19, 2018
 *      Author: ax
 */
#define MODULE "[MM]: "

#include <stdlib.h>

#include <Console.h>


static unsigned addr;
static short width = 1;
static short size = 0x10;


union {
    char  c[16];
    short s[8];
    int   w[4];
} x;


int mw(int argc, void* argv[]) {
    width = atoi(argv[1]);
    Console_printf(MODULE"set memory width to %d.\n", width);

    return 0;
}

void displayLine(unsigned addr) {
    memcpy(&x, (void*) (addr & 0xFFFFFFF0), 16);

    Console_printf("%08x: ", addr);

    switch (width) {
    case 8:
        Console_printf("%02x%02x%02x%02x%02x%02x%02x%-02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
#if (ENDIAN == _BE)
               x.c[0], x.c[1], x.c[2], x.c[3], x.c[4], x.c[5], x.c[6], x.c[7],
               x.c[8], x.c[9], x.c[10], x.c[11], x.c[12], x.c[13], x.c[14], x.c[15]);
#else
        x.c[7], x.c[6], x.c[5], x.c[4], x.c[3], x.c[2], x.c[1], x.c[0],
        x.c[15], x.c[14], x.c[13], x.c[12], x.c[11], x.c[10], x.c[9], x.c[8]);
#endif
        break;
    case 4:
        Console_printf("%08x %08x %08x %08x\n",
               x.w[0], x.w[1], x.w[2], x.w[3]);
        break;
    case 2:
        Console_printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
               x.s[0], x.s[1], x.s[2], x.s[3], x.s[4], x.s[5], x.s[6], x.s[7]);
        break;
    case 0:
        Console_printf("%c-%c-%c-%c-%c-%c-%c-%c-%c-%c-%c-%c-%c-%c-%c-%c\n",
              x.c[0], x.c[1], x.c[2], x.c[3], x.c[4], x.c[5], x.c[6], x.c[7],
              x.c[8], x.c[9], x.c[10], x.c[11], x.c[12], x.c[13], x.c[14], x.c[15]);
        break;
    case 1:
    default:
        Console_printf("%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
              x.c[0], x.c[1], x.c[2], x.c[3], x.c[4], x.c[5], x.c[6], x.c[7],
              x.c[8], x.c[9], x.c[10], x.c[11], x.c[12], x.c[13], x.c[14], x.c[15]);
    }
}

int md(int argc, void* argv[]) {
    unsigned to = (argc > 1) ? atoi(argv[1]) : addr + size;
    unsigned sz = (argc > 2) ? atoi(argv[2]) : size;

    unsigned term = to + sz;
    while (term < to) {
        displayLine(to);
        to += 0x10;
    }

    return 0;
}

int mm(int argc, void* argv[]) {
    unsigned to = atol(argv[1]);

    switch (width) {
    case 1:
        *(char*) to = (char) atoi(argv[2]);
        break;
    case 2:
        *(short*) to = (short) atoi(argv[2]);
        break;
    case 8:
        *(long long*) to = strtoll(argv[2], NULL, 0);
        break;
    case 4:
    default:
        *(int*) to = atoi(argv[2]);
    }

    displayLine(to);

    return 0;
}
